"""
AST(抽象语法树节点) abstract syntax tree
"""
from tokens import Token


class Node(object):
    def __init__(self):
        self.pos_end = None
        self.pos_start = None

    pass


class VarAccessNode(Node):
    # 变量访问节点
    def __init__(self, var_name_token: Token):
        super().__init__()
        self.var_name_token = var_name_token
        self.pos_start = var_name_token.pos_start
        self.pos_end = var_name_token.pos_end

    def __repr__(self):
        return f'{self.var_name_token}'


class VarAssignNode(Node):
    # 为变量分配值的节点 var a = 10
    def __init__(self, var_name_token: Token, value_node: Node):
        """
        var_name_token: 变量名对应的 token
        value_node: 变量值对应的节点
        """
        super().__init__()
        self.var_name_token = var_name_token
        self.value_node = value_node
        self.pos_start = var_name_token.pos_start
        self.pos_end = var_name_token.pos_end

    def __repr__(self):
        return f'{self.var_name_token} = {self.value_node}'

    def copy(self):
        return VarAssignNode(self.var_name_token, self.value_node)


class NumberNode(Node):
    # 数字节点
    def __init__(self, token: Token):
        super().__init__()
        self.token = token
        self.pos_start = self.token.pos_start
        self.pos_end = self.token.pos_end

    def __repr__(self):
        return f'{self.token}'


class BinOpNode(Node):
    # 二元操作节点 + - * / , 1 + 2 ==> left_node = NumberNode(1), right_node = NumberNode(2), token = +
    def __init__(self, left_node, op_token, right_node):
        """
        :param left_node: 左节点
        :param op_token: 操作符
        :param right_node: 右节点
        """
        super().__init__()
        self.op_token = op_token
        self.left_node = left_node
        self.right_node = right_node
        self.pos_start = self.op_token.pos_start
        self.pos_end = self.op_token.pos_end

    def __repr__(self):
        return f'({self.left_node} - {self.op_token} - {self.right_node})'


class UnaryOpNode(Node):

    # 一元操作, 如负数
    def __init__(self, op_token, node):
        """
        :param op_token: 正号或符号
        :param node: 右节点
        """
        super().__init__()
        self.op_token = op_token
        self.node = node
        self.pos_start = self.op_token.pos_start
        self.pos_end = self.op_token.pos_end

    def __repr__(self):
        return f'({self.op_token} - {self.node})'


class IfNode(Node):
    # if代码对应的代码块
    def __init__(self, case: list[tuple[Node, Node, bool]], else_case: tuple[Node, bool]):
        super().__init__()
        self.case = case
        self.else_case = else_case
        # 因为if判断可以有多层，所以case是二元数组
        self.pos_start = self.case[0][0].pos_start
        # 第二个判断的开始位置，为第一个判断的最后一个位置
        self.pos_end = (self.else_case or self.case[len(self.case) - 1][0].pos_end)

    def __repr__(self):
        result = ''
        if self.case:
            condition, expr, should_return_null = self.case[0]
            result += f'if {condition} then {expr}'
        for condition, expr in self.case[1:]:
            result += f' elif {condition} then {expr}'
        if self.else_case:
            result += f' else {self.else_case}'
        return f'({result})'


class ForNode(Node):
    """for循环对应的节点"""

    def __init__(self, var_name_token: Token, start_value_node: Node, end_value_node: Node, step_value_node: Node,
                 body_node: Node, should_return_null):
        """

        :param var_name_token: 循环变量
        :param start_value_node: 起始值
        :param end_value_node: 终止值
        :param step_value_node: 每次循环跳跃
        :param body_node: 循环体逻辑
        :param should_return_null: 是否返回null，for循环内有多行时，该值为True
        """
        super().__init__()
        self.var_name_token = var_name_token
        self.start_value_node = start_value_node
        self.end_value_node = end_value_node
        self.step_value_node = step_value_node
        self.body_node = body_node
        self.should_return_null = should_return_null
        self.pos_start = self.var_name_token.pos_start
        self.pos_end = self.body_node.pos_end


class WhileNode(Node):
    """while循环对应的节点"""

    def __init__(self, condition_node, body_node, should_return_null):
        """

        :param condition_node: while关键字后的条件语句
        :param body_node: while循环体中逻辑
        :param should_return_null: 是否返回null，while循环内有多行时，该值为True
        """
        super().__init__()
        self.condition_node = condition_node
        self.body_node = body_node
        self.should_return_null = should_return_null
        self.pos_start = self.condition_node.pos_start
        self.pos_end = self.body_node.pos_end


class FuncNode(Node):
    """func函数对应的节点"""

    def __init__(self, var_name_token: Token, arg_name_tokens: list, body_node: Node, should_auto_return):
        """

        :param var_name_token: 函数名
        :param arg_name_tokens: 函数参数
        :param body_node: 函数体
        :param should_auto_return: 是否为多行函数, False 为 是
        """
        super().__init__()
        self.var_name_token = var_name_token
        self.arg_name_tokens = arg_name_tokens
        self.body_node = body_node
        self.should_auto_return = should_auto_return
        if self.var_name_token:  # 函数有函数名时
            self.pos_start = self.var_name_token.pos_start
        elif len(self.arg_name_tokens) > 0:  # 函数无函数名, 但是有参数时
            self.pos_start = self.arg_name_tokens[0].pos_start
        else:  # 函数无函数名无参数
            self.pos_start = self.body_node.pos_start

        self.pos_end = self.body_node.pos_end


class CallNode(Node):
    """调用func函数对应的节点"""

    def __init__(self, node_to_call: Node, arg_nodes: list):
        """

        :param node_to_call: 函数名
        :param arg_nodes: 函数参数
        """
        super().__init__()
        self.node_to_call = node_to_call
        self.arg_nodes = arg_nodes
        self.pos_start = node_to_call.pos_start

        if len(arg_nodes) > 0:
            self.pos_end = self.arg_nodes[len(self.arg_nodes) - 1].pos_end
        else:
            self.pos_end = self.node_to_call.pos_end


class StringNode(Node):
    """string字符串对应的节点"""

    def __init__(self, token):
        super().__init__()
        self.token = token
        self.pos_start = token.pos_start
        self.pos_end = token.pos_end

    def __repr__(self):
        return f'{self.token}'


class ListNode(Node):
    """list列表对应的节点"""

    def __init__(self, element_nodes, pos_start, pos_end):
        super().__init__()
        self.element_nodes = element_nodes
        self.pos_start = pos_start
        self.pos_end = pos_end

    def __repr__(self):
        return f'{self.element_nodes}'


class ReturnNode(object):
    def __init__(self, node_to_return, pos_start, pos_end):
        """

        :param node_to_return: return关键字后的expr对象
        :param pos_start:
        :param pos_end:
        """
        self.node_to_return = node_to_return
        self.pos_start = pos_start
        self.pos_end = pos_end


class ContinueNode(object):
    """
    continue操作，跳过此次循环
    """

    def __init__(self, pos_start, pos_end):
        self.pos_start = pos_start
        self.pos_end = pos_end


class BreakNode(object):
    """
    break操作，跳出整个循环
    """

    def __init__(self, pos_start, pos_end):
        self.pos_start = pos_start
        self.pos_end = pos_end
